package handlers

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"time"

	"data_service/models"
	"data_service/server"
	"data_service/utils"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

// WebSocket升级器
var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true // 允许所有来源，生产环境应该检查具体域名
	},
}

// 客户端连接结构
type Client struct {
	ID       string
	UserID   uint64
	UserName string
	Socket   *websocket.Conn
	Send     chan []byte
	Hub      *Hub
}

// Hub 管理所有客户端连接
type Hub struct {
	clients     map[*Client]bool
	register    chan *Client
	unregister  chan *Client
	broadcast   chan []byte
	rooms       map[string]map[*Client]bool
	chatService *server.ChatService
}

// 创建新的Hub
func NewHub(chatService *server.ChatService) *Hub {
	return &Hub{
		clients:     make(map[*Client]bool),
		register:    make(chan *Client),
		unregister:  make(chan *Client),
		broadcast:   make(chan []byte),
		rooms:       make(map[string]map[*Client]bool),
		chatService: chatService,
	}
}

// 广播当前在线用户列表
func (h *Hub) broadcastOnlineUsers() {
	// 去重后的在线用户列表
	usersMap := make(map[uint64]string)
	for c := range h.clients {
		usersMap[c.UserID] = c.UserName
	}
	users := make([]map[string]interface{}, 0, len(usersMap))
	for uid, name := range usersMap {
		users = append(users, map[string]interface{}{
			"user_id":   uid,
			"user_name": name,
		})
	}
	// 构造消息
	msg := h.chatService.CreateWebSocketResponse("online_users", map[string]interface{}{
		"users": users,
	})
	messageBytes, _ := json.Marshal(msg)
	// 发送给所有客户端
	for client := range h.clients {
		select {
		case client.Send <- messageBytes:
		default:
			close(client.Send)
			delete(h.clients, client)
		}
	}
}

// 启动Hub
func (h *Hub) Run() {
	for {
		select {
		case client := <-h.register:
			h.clients[client] = true
			fmt.Printf("[CHAT] 客户端连接: %s (用户: %s)\n", client.ID, client.UserName)

			// 添加在线用户到数据库
			onlineUser := &models.OnlineUser{
				UserID:   uint(client.UserID),
				SocketID: client.ID,
				UserName: client.UserName,
				IsOnline: true,
				LastSeen: time.Now(),
			}
			if err := h.chatService.AddOnlineUser(onlineUser); err != nil {
				fmt.Printf("[CHAT] 添加在线用户失败: %v\n", err)
			}

			// 广播在线用户列表
			h.broadcastOnlineUsers()

		case client := <-h.unregister:
			if _, ok := h.clients[client]; ok {
				delete(h.clients, client)
				close(client.Send)
				fmt.Printf("[CHAT] 客户端断开: %s (用户: %s)\n", client.ID, client.UserName)

				// 从数据库移除在线用户
				if err := h.chatService.RemoveOnlineUser(client.ID); err != nil {
					fmt.Printf("[CHAT] 移除在线用户失败: %v\n", err)
				}

				// 从所有房间中移除
				for roomID, roomClients := range h.rooms {
					if _, ok := roomClients[client]; ok {
						delete(roomClients, client)
						if len(roomClients) == 0 {
							delete(h.rooms, roomID)
						}
					}
				}

				// 广播在线用户列表
				h.broadcastOnlineUsers()
			}

		case message := <-h.broadcast:
			for client := range h.clients {
				select {
				case client.Send <- message:
				default:
					close(client.Send)
					delete(h.clients, client)
				}
			}
		}
	}
}

// 客户端读取消息
func (c *Client) readPump() {
	defer func() {
		c.Hub.unregister <- c
		c.Socket.Close()
	}()

	c.Socket.SetReadLimit(512)
	c.Socket.SetReadDeadline(time.Now().Add(60 * time.Second))
	c.Socket.SetPongHandler(func(string) error {
		c.Socket.SetReadDeadline(time.Now().Add(60 * time.Second))
		return nil
	})

	for {
		_, messageBytes, err := c.Socket.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
				fmt.Printf("[CHAT] WebSocket错误: %v\n", err)
			}
			break
		}

		// 解析消息
		wsMessage, err := c.Hub.chatService.ParseWebSocketMessage(messageBytes)
		if err != nil {
			fmt.Printf("[CHAT] 解析消息错误: %v\n", err)
			continue
		}

		// 处理不同类型的消息
		c.handleMessage(wsMessage)
	}
}

// 客户端写入消息
func (c *Client) writePump() {
	ticker := time.NewTicker(54 * time.Second)
	defer func() {
		ticker.Stop()
		c.Socket.Close()
	}()

	for {
		select {
		case message, ok := <-c.Send:
			c.Socket.SetWriteDeadline(time.Now().Add(10 * time.Second))
			if !ok {
				c.Socket.WriteMessage(websocket.CloseMessage, []byte{})
				return
			}

			w, err := c.Socket.NextWriter(websocket.TextMessage)
			if err != nil {
				return
			}
			w.Write(message)

			// 批量发送消息
			n := len(c.Send)
			for i := 0; i < n; i++ {
				w.Write([]byte{'\n'})
				w.Write(<-c.Send)
			}

			if err := w.Close(); err != nil {
				return
			}

		case <-ticker.C:
			c.Socket.SetWriteDeadline(time.Now().Add(10 * time.Second))
			if err := c.Socket.WriteMessage(websocket.PingMessage, nil); err != nil {
				return
			}
		}
	}
}

// 处理WebSocket消息
func (c *Client) handleMessage(wsMessage *server.WebSocketMessage) {
	switch wsMessage.Type {
	case "join_room":
		c.handleJoinRoom(wsMessage.Data)
	case "leave_room":
		c.handleLeaveRoom(wsMessage.Data)
	case "message":
		c.handleChatMessage(wsMessage.Data)
	case "ping":
		c.handlePing()
	case "get_online_users":
		c.handleGetOnlineUsers()
	}
}

// 处理加入房间
func (c *Client) handleJoinRoom(data interface{}) {
	dataBytes, _ := json.Marshal(data)
	var joinReq server.JoinRoomRequest
	json.Unmarshal(dataBytes, &joinReq)

	// 确保房间存在
	room, err := c.Hub.chatService.GetChatRoom(joinReq.RoomID)
	if err != nil {
		// 房间不存在，创建新房间
		room = &models.ChatRoom{
			RoomID:    joinReq.RoomID,
			RoomName:  "聊天房间",
			RoomType:  models.RoomTypePrivate,
			CreatedBy: uint(c.UserID),
		}
		if err := c.Hub.chatService.CreateChatRoom(room); err != nil {
			fmt.Printf("[CHAT] 创建房间失败: %v\n", err)
			return
		}
	}

	// 添加到房间
	if c.Hub.rooms[joinReq.RoomID] == nil {
		c.Hub.rooms[joinReq.RoomID] = make(map[*Client]bool)
	}
	c.Hub.rooms[joinReq.RoomID][c] = true

	// 发送确认消息
	response := c.Hub.chatService.CreateWebSocketResponse("room_joined", map[string]interface{}{
		"room_id": joinReq.RoomID,
		"message": "已加入房间",
	})
	c.sendMessage(response)

	// 记录日志
	c.Hub.chatService.LogChatActivity(c.UserID, "join_room", joinReq.RoomID)
	fmt.Printf("[CHAT] 用户 %s 加入房间 %s\n", c.UserName, joinReq.RoomID)
}

// 处理离开房间
func (c *Client) handleLeaveRoom(data interface{}) {
	dataBytes, _ := json.Marshal(data)
	var leaveReq server.LeaveRoomRequest
	json.Unmarshal(dataBytes, &leaveReq)

	// 从房间中移除
	if roomClients, ok := c.Hub.rooms[leaveReq.RoomID]; ok {
		delete(roomClients, c)
		if len(roomClients) == 0 {
			delete(c.Hub.rooms, leaveReq.RoomID)
		}
	}

	// 发送确认消息
	response := c.Hub.chatService.CreateWebSocketResponse("room_left", map[string]interface{}{
		"room_id": leaveReq.RoomID,
		"message": "已离开房间",
	})
	c.sendMessage(response)

	// 记录日志
	c.Hub.chatService.LogChatActivity(c.UserID, "leave_room", leaveReq.RoomID)
	fmt.Printf("[CHAT] 用户 %s 离开房间 %s\n", c.UserName, leaveReq.RoomID)
}

// 处理聊天消息
func (c *Client) handleChatMessage(data interface{}) {
	dataBytes, _ := json.Marshal(data)
	var msgReq server.ChatMessageRequest
	json.Unmarshal(dataBytes, &msgReq)

	// 创建消息记录
	message := &models.ChatMessage{
		RoomID:      msgReq.RoomID,
		UserID:      uint(c.UserID),
		UserName:    c.UserName,
		Content:     msgReq.Content,
		MessageType: msgReq.MessageType,
		Timestamp:   time.Now(),
	}

	// 保存到数据库
	if err := c.Hub.chatService.CreateChatMessage(message); err != nil {
		fmt.Printf("[CHAT] 保存消息失败: %v\n", err)
		return
	}

	// 创建响应消息
	response := c.Hub.chatService.CreateWebSocketResponse("message", server.ChatMessageResponse{
		ID:          message.ID,
		RoomID:      message.RoomID,
		UserID:      message.UserID,
		UserName:    message.UserName,
		Content:     message.Content,
		MessageType: message.MessageType,
		Timestamp:   message.Timestamp,
	})

	// 发送给房间内的所有用户
	c.broadcastToRoom(msgReq.RoomID, response)

	// 记录日志
	c.Hub.chatService.LogChatActivity(c.UserID, "send_message", msgReq.RoomID)
}

// 处理心跳
func (c *Client) handlePing() {
	response := c.Hub.chatService.CreateWebSocketResponse("pong", map[string]interface{}{
		"message": "pong",
	})
	c.sendMessage(response)
}

// 处理获取在线用户列表请求
func (c *Client) handleGetOnlineUsers() {
	// 去重后的在线用户列表
	usersMap := make(map[uint64]string)
	for client := range c.Hub.clients {
		usersMap[client.UserID] = client.UserName
	}
	users := make([]map[string]interface{}, 0, len(usersMap))
	for uid, name := range usersMap {
		users = append(users, map[string]interface{}{
			"user_id":   uid,
			"user_name": name,
		})
	}

	// 发送在线用户列表给请求的客户端
	response := c.Hub.chatService.CreateWebSocketResponse("online_users", map[string]interface{}{
		"users": users,
	})
	c.sendMessage(response)

	fmt.Printf("[CHAT] 用户 %s 请求在线用户列表，共 %d 人在线\n", c.UserName, len(users))
}

// 发送消息给客户端
func (c *Client) sendMessage(message *server.WebSocketMessage) {
	messageBytes, _ := json.Marshal(message)
	select {
	case c.Send <- messageBytes:
	default:
		close(c.Send)
		delete(c.Hub.clients, c)
	}
}

// 广播消息到房间
func (c *Client) broadcastToRoom(roomID string, message *server.WebSocketMessage) {
	messageBytes, _ := json.Marshal(message)

	if roomClients, ok := c.Hub.rooms[roomID]; ok {
		for client := range roomClients {
			select {
			case client.Send <- messageBytes:
			default:
				close(client.Send)
				delete(c.Hub.clients, client)
				delete(roomClients, client)
			}
		}
	}
}

// WebSocket连接处理
func HandleWebSocket(hub *Hub) gin.HandlerFunc {
	return func(c *gin.Context) {
		conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
		if err != nil {
			fmt.Printf("[CHAT] WebSocket升级失败: %v\n", err)
			return
		}

		// 生成客户端ID
		clientID := c.Query("client_id")
		if clientID == "" {
			clientID = generateClientID()
		}

		// 获取用户信息（这里简化处理，实际应该从token验证）
		userIDStr := c.Query("user_id")
		userName := c.Query("user_name")
		if userIDStr == "" || userName == "" {
			fmt.Printf("[CHAT] 缺少用户信息\n")
			conn.Close()
			return
		}

		userID, err := strconv.ParseUint(userIDStr, 10, 64)
		if err != nil {
			fmt.Printf("[CHAT] 用户ID格式错误: %v\n", err)
			conn.Close()
			return
		}

		client := &Client{
			ID:       clientID,
			UserID:   userID,
			UserName: userName,
			Socket:   conn,
			Send:     make(chan []byte, 256),
			Hub:      hub,
		}

		client.Hub.register <- client

		// 启动读写协程
		go client.writePump()
		go client.readPump()
	}
}

// 生成客户端ID
func generateClientID() string {
	return time.Now().Format("20060102150405") + "-" + randomString(6)
}

// 生成随机字符串
func randomString(length int) string {
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, length)
	for i := range b {
		b[i] = charset[time.Now().UnixNano()%int64(len(charset))]
	}
	return string(b)
}

// GetChatMessages 获取聊天消息的HTTP接口
func GetChatMessages(c *gin.Context) {
	fmt.Printf("[CHAT] 收到获取消息请求 - IP: %s\n", c.ClientIP())

	roomID := c.Query("room_id")
	if roomID == "" {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    "MISSING_ROOM_ID",
			"message": "房间ID不能为空",
			"data":    nil,
		})
		return
	}

	limit := 50
	offset := 0

	if limitStr := c.Query("limit"); limitStr != "" {
		if l, err := strconv.Atoi(limitStr); err == nil {
			limit = l
		}
	}
	if offsetStr := c.Query("offset"); offsetStr != "" {
		if o, err := strconv.Atoi(offsetStr); err == nil {
			offset = o
		}
	}

	// 获取聊天服务实例
	chatService := server.NewChatService(models.GetDB())
	messages, err := chatService.GetChatMessages(roomID, limit, offset)
	if err != nil {
		fmt.Printf("[CHAT] 获取消息失败: %v\n", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    "GET_MESSAGES_FAILED",
			"message": "获取消息失败",
			"data":    nil,
		})
		return
	}

	fmt.Printf("[CHAT] 成功获取 %d 条消息\n", len(messages))
	c.JSON(http.StatusOK, gin.H{
		"code":    "SUCCESS",
		"message": "获取消息成功",
		"data":    messages,
	})
}

// GetOnlineUsers 获取在线用户的HTTP接口
func GetOnlineUsers(c *gin.Context) {
	fmt.Printf("[CHAT] 收到获取在线用户请求 - IP: %s\n", c.ClientIP())

	// 获取聊天服务实例
	chatService := server.NewChatService(models.GetDB())
	users, err := chatService.GetOnlineUsers()
	if err != nil {
		fmt.Printf("[CHAT] 获取在线用户失败: %v\n", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    "GET_ONLINE_USERS_FAILED",
			"message": "获取在线用户失败",
			"data":    nil,
		})
		return
	}

	fmt.Printf("[CHAT] 成功获取 %d 个在线用户\n", len(users))
	c.JSON(http.StatusOK, gin.H{
		"code":    "SUCCESS",
		"message": "获取在线用户成功",
		"data":    users,
	})
}

// 创建房间
func CreateChatRoomHandler(c *gin.Context) {
	var req struct {
		RoomID   string `json:"room_id"`
		RoomName string `json:"room_name"`
		RoomType string `json:"room_type"` // private 或 group
		UserID   uint   `json:"user_id" binding:"required"`
	}
	if err := utils.BindJSON(c, &req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": "INVALID_JSON_FORMAT", "message": "请求参数格式错误"})
		return
	}

	// 如果未指定 RoomID，生成一个
	if req.RoomID == "" {
		req.RoomID = time.Now().Format("20060102150405") + "-room"
	}
	if req.RoomType == "" {
		req.RoomType = models.RoomTypePrivate
	}

	room := &models.ChatRoom{
		RoomID:    req.RoomID,
		RoomName:  req.RoomName,
		RoomType:  req.RoomType,
		CreatedBy: req.UserID,
		IsActive:  true,
	}
	if err := server.NewChatService(models.GetDB()).CreateChatRoom(room); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": "CREATE_ROOM_FAILED", "message": "创建房间失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": "创建房间成功", "data": room})
}

// 获取用户房间列表
func GetUserRoomsHandler(c *gin.Context) {
	userIDStr := c.Query("user_id")
	if userIDStr == "" {
		c.JSON(http.StatusBadRequest, gin.H{"code": "MISSING_USER_ID", "message": "用户ID不能为空"})
		return
	}
	userID64, err := strconv.ParseUint(userIDStr, 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": "INVALID_USER_ID", "message": "用户ID格式错误"})
		return
	}
	chatService := server.NewChatService(models.GetDB())
	rooms, err := chatService.GetUserChatRooms(uint(userID64))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": "GET_ROOMS_FAILED", "message": "获取房间列表失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": "获取房间列表成功", "data": rooms})
}
